import logging

from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.models import User
from django.core.cache import cache
# Create your views here.
from django.db.models import F
from django.shortcuts import render
from rest_framework import mixins, status
from rest_framework.authtoken.models import Token
from rest_framework.exceptions import AuthenticationFailed, ValidationError
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet, GenericViewSet, ReadOnlyModelViewSet

from blog.filters.blog_filter import BlogFilterSet
from blog.models import Blog, Comment
from blog.serializers import BlogListSerializer, BlogDetailSerializer, BlogPostSerializer, UserRegisterSerializer, \
    CommentSerializer, CommentListSerializer, UserLoginSerializer
from blog.utils import MultiSerializerViewSetMixin
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly

logger = logging.getLogger(__name__)


class BlogView(MultiSerializerViewSetMixin, mixins.ListModelMixin,
               mixins.RetrieveModelMixin, mixins.CreateModelMixin, GenericViewSet):
    throttle_scope = 'blog_view'
    authentication_classes = {TokenAuthentication}
    permission_classes = (IsAuthenticatedOrReadOnly,)
    queryset = Blog.objects.all()
    serializer_action_classes = {
        'list': BlogListSerializer,
        'retrieve': BlogDetailSerializer,
        'create': BlogPostSerializer
    }

    # filter_fields = {'tags', }
    filter_class = BlogFilterSet
    search_fields = ('title',)

    # def get_queryset(self):
    #     id_list = self.request.GET.getlist("tags__contains")
    #     if not id_list:
    #         return Blog.objects.all()
    #     print("=====")
    #     print(id_list)
    #     return Blog.objects.filter(tags__contains=id_list)

    def retrieve(self, request, *args, **kwargs):
        instance = cache.get('blog:%s' % kwargs['pk'])
        if not instance:
            instance = self.get_object()
            cache.set('blog:%s' % kwargs['pk'], instance)
        serializer = self.get_serializer(instance)
        Blog.objects.filter(pk=instance.id).update(read_num=F('read_num') + 1)
        return Response(serializer.data)


class CommentView(MultiSerializerViewSetMixin,
                  mixins.CreateModelMixin,
                  mixins.ListModelMixin,
                  GenericViewSet):
    authentication_classes = {TokenAuthentication}
    permission_classes = (IsAuthenticatedOrReadOnly,)
    queryset = Comment.objects.all()
    filter_fields = ('blog',)
    serializer_action_classes = {
        'list': CommentListSerializer,
        'create': CommentSerializer
    }

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        blog = self.request.query_params.get('blog', None)
        if blog is None:
            msg = 'blog field is required'
            raise ValidationError(msg)
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class LoginTokenView(GenericAPIView):
    queryset = User.objects.all()
    serializer_class = UserLoginSerializer

    def post(self, request):
        user = authenticate(request, username=request.data.get('username'), password=request.data.get('password'))
        if not user:
            msg = 'Invalid username or password.'
            raise AuthenticationFailed(msg)
        login(request, user)
        token, created = Token.objects.get_or_create(user=user)
        # request.session['user_id'] = user.id
        return Response({'token': token.key, 'username': user.username, 'id': user.id})


class RegisterView(mixins.CreateModelMixin, mixins.ListModelMixin, GenericViewSet):
    queryset = User.objects.all()
    serializer_class = UserRegisterSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = User.objects.create_user(serializer.validated_data.get('username'),
                                        password=serializer.validated_data.get('password'),
                                        email=serializer.validated_data.get('email'),
                                        is_staff=True)
        login(request, user)
        headers = self.get_success_headers(serializer.data)
        token, created = Token.objects.get_or_create(user=user)
        return Response({'token': token.key, 'username': user.username, 'id': user.id})
        # return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)


class LogoutView(APIView):
    # queryset = User.objects.all()
    # serializer_class = UserLoginSerializer

    def post(self, request):
        logout(request)
        return Response()

